package com.md.application.assembler;

import com.md.domain.model.po.Role;
import com.md.exception.ServerException;
import com.md.model.po.Users;
import com.md.model.request.authentication.users.LoginRequest;
import com.md.model.request.authentication.users.RegisterUsersRequest;
import com.md.model.request.authentication.users.UpdateUsersRequest;
import com.md.model.response.authentication.users.InternalUsersResponse;
import com.md.model.response.authentication.users.UsersLoginResponse;
import com.md.model.response.authentication.users.UsersResponse;
import com.md.util.ClassUtils;
import com.md.util.DateUtils;
import com.md.util.EncryptionUtils;
import com.md.util.ObjectUtil;
import com.md.value.constants.MatchConstants;
import com.md.value.enums.ErrorEnum;
import com.md.value.enums.LoginEnum;
import com.md.value.enums.SexEnum;
import lombok.experimental.UtilityClass;
import org.springframework.util.ObjectUtils;

import java.time.LocalDateTime;
import java.util.Optional;

/**
 * @author 刘骄阳
 * 2022-12-21 17:35
 */
@UtilityClass
public class UsersAssembler {

  /**
   * 构建登录po
   *
   * @param account  账号
   * @param password 密码
   * @param phone    手机号
   * @return 登录用的po
   */
  public static Users buildLogin(final String account, final String password, final String phone) {
    Users temp = new Users();
    temp.setAccount(account);
    Optional.ofNullable(password).ifPresent(value -> temp.setPassword(buildPassword(account, password)));
    temp.setPhone(phone);
    return temp;
  }

  /**
   * 构建登录po
   *
   * @param phone 手机号
   * @return 登录用的po
   */
  public static Users buildRegister(final String name, final String headIcon, final String phone, final SexEnum sex) {
    Users temp = new Users();
    temp.setHeadIcon(headIcon);
    temp.setSex(Optional.ofNullable(sex).orElse(SexEnum.OTHER).getCode());
    temp.setPhone(phone);
    temp.setName(name);
    return temp;
  }

  /**
   * 构建查询用户的请求实体
   *
   * @param phone   手机号
   * @param name    用户名
   * @param account 账号
   * @param roleId  角色
   * @return 查询用的PO
   */
  public static Users buildQueryUsers(final String phone, final String name, final String account,
                                      final Long roleId) {
    Users users = new Users();
    users.setPhone(phone);
    users.setName(name);
    users.setAccount(account);
    users.setRoleId(roleId);
    return users;
  }

  /**
   * 构建密码
   *
   * @param account  账号
   * @param password 密码
   * @return 加密后的密码
   */
  public static String buildPassword(final String account, final String password) {
    return EncryptionUtils.md5Encryption(password, account);
  }

  /**
   * 构建登录响应实体
   *
   * @param users 用户po
   * @return 登录响应实体
   */
  public static UsersLoginResponse buildUsersLoginResponse(final Users users) {
    UsersLoginResponse response = new UsersLoginResponse();
    String token = EncryptionUtils.jwtEncryption(users);
    response.setToken(token);
    response.setHeadIcon(users.getHeadIcon());
    response.setName(users.getName());
    return response;
  }

  /**
   * 校验登录参数是否正确
   *
   * @param request 登录参数
   */
  public static void judgeLoginRequest(final LoginRequest request) {
    LoginEnum method = request.getLoginMethod();
    if (ObjectUtil.isEmpty(method)) {
      throw ServerException.build(ErrorEnum.IS_EMPTY, "登录方式");
    }
    switch (request.getLoginMethod()) {
      case ACCOUNT_PASSWORD:
        if (ObjectUtil.hasEmpty(request.getAccount(), request.getPassword())) {
          throw ServerException.build(ErrorEnum.IS_EMPTY, "账号或密码");
        }
        if (!request.getPassword().matches(MatchConstants.PASSWORD)) {
          throw ServerException.build(ErrorEnum.LOGIN_ERROR, "密码长度应在8-12位!");
        }
        break;
      case PHONE_CODE:
        if (ObjectUtil.hasEmpty(request.getPhone(), request.getCode())) {
          throw ServerException.build(ErrorEnum.IS_EMPTY, "手机号或验证码");
        }
        if (!request.getPhone().matches(MatchConstants.PHONE)) {
          throw ServerException.build(ErrorEnum.LOGIN_ERROR, "手机号格式错误!");
        }
        break;
      case PHONE_PASSWORD:
        if (ObjectUtil.hasEmpty(request.getPhone(), request.getPassword())) {
          throw ServerException.build(ErrorEnum.IS_EMPTY, "手机号或密码");
        }
        if (!request.getPhone().matches(MatchConstants.PHONE)) {
          throw ServerException.build(ErrorEnum.LOGIN_ERROR, "手机号格式错误!");
        }
        if (!request.getPassword().matches(MatchConstants.PASSWORD)) {
          throw ServerException.build(ErrorEnum.LOGIN_ERROR, "密码长度应在8-12位!");
        }
        break;
      default:
        throw ServerException.build(ErrorEnum.LOGIN_ERROR, "错误的登录方式!");
    }
  }

  public static void judgeRegisterRequest(final RegisterUsersRequest request) {
    if (!ObjectUtils.isEmpty(request.getPhone()) && (!request.getPhone().matches(MatchConstants.PHONE))) {
      throw ServerException.build(ErrorEnum.LOGIN_ERROR, "手机号格式错误!");

    }
  }

  public static UsersLoginResponse buildUsersToLoginResponse(final Users users) {
    if (users == null) {
      throw ServerException.build(ErrorEnum.USER_NOT_EXISTS);
    }
    // 校验是否冻结
    LocalDateTime frozen = users.getFrozen();
    LocalDateTime now = LocalDateTime.now();
    if (!ObjectUtils.isEmpty(frozen) && frozen.isAfter(now)) {
      // 如果冻结时间不为空,并且在当前时间之后
      throw ServerException.build(ErrorEnum.USER_UNAVAILABLE, DateUtils.timeDifference(frozen, now));
    }
    return buildUsersLoginResponse(users);
  }

  public static Users buildUpdatePo(final UpdateUsersRequest request) {
    return ClassUtils.source2Target(request, Users.class);
  }

  public static UsersResponse buildUserResponse(final Users users, final Role role) {
    UsersResponse usersResponse = ClassUtils.source2Target(users, UsersResponse.class);
    usersResponse.setSex(SexEnum.of(users.getSex()));
    Optional.ofNullable(usersResponse.getPhone()).ifPresent(phone ->
      usersResponse.setPhone(phone.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2")));
    Optional.ofNullable(role).ifPresent(roleInfo -> usersResponse.setRoleDetailResponse(RoleAssembler.
      buildRoleDetailResponse(role)));
    return usersResponse;
  }

  public static InternalUsersResponse buildInternalUserResponse(final Users users) {
    InternalUsersResponse internalUsersResponse = ClassUtils.source2Target(users, InternalUsersResponse.class);
    internalUsersResponse.setSex(SexEnum.of(users.getSex()));
    Optional.ofNullable(internalUsersResponse.getPhone()).ifPresent(phone ->
      internalUsersResponse.setPhone(phone.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2")));
    return internalUsersResponse;
  }
}
